package com.common.util;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.Locale;
import java.util.Random;
import java.util.ResourceBundle;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.multipart.MultipartFile;

import com.common.exception.BusinessException;

/**
 * 上传控制器
 * 
 * @author lmk
 *
 */
public class FileUpload {

    private static Logger logger = LogManager.getLogger(FileUpload.class);

    public static final String IMAGE = "image";
    public static final String FLASH = "flash";
    public static final String MEDIA = "media";
    public static final String FILE = "file";
    
    private static final String COMMA = ",";
    /**
     * 上传
     * @return
     * @throws Exception
     */
    public static String fileUpload(HttpServletRequest request, String identifier, MultipartFile file)
            throws Exception {
        // 读取imgPath配置文件
        ResourceBundle rb = ResourceBundle.getBundle ( "sysConfig" , Locale.getDefault ());
        //硬盘存放路径
        String savePath = rb.getString( "fileRealPath" ); 
        //相对路径
        String saveUrl = rb.getString( "filePath" ); 
        String url = "";
        // 定义允许上传的文件扩展名
        HashMap<String, String> extMap = new HashMap<String, String>(16);
        HashMap<String, String> map = new HashMap<String, String>(16);
        map = getType(identifier);
        extMap.putAll(map);

        // 最大文件大小
        long maxSize = 20971520;

        if (!ServletFileUpload.isMultipartContent(request)) {
            throw new RuntimeException("请选择文件");
        }
        // 检查目录
        File uploadDir = new File(savePath);
        if (!uploadDir.isDirectory()) {
            throw new RuntimeException("上传目录不存在");
        }
        // 检查目录写权限
        if (!uploadDir.canWrite()) {
            throw new RuntimeException("上传目录没有写权限");
        }

        String dirName = null;

        if (IMAGE.equals(identifier)) {
            dirName = "image";
        } else if (FLASH.equals(identifier)) {
            dirName = "flash";
        } else if (MEDIA.equals(identifier)) {
            dirName = "media";
        } else if (FILE.equals(identifier)) {
            dirName = "file";
        }
        if (!extMap.containsKey(dirName)) {
            throw new RuntimeException("目录名不正确");
        }
        // 创建文件夹
       /* savePath += dirName + "/";
        saveUrl += dirName + "/";
        File saveDirFile = new File(savePath);
        if (!saveDirFile.exists()) {
            saveDirFile.mkdirs();
        }
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
        String ymd = sdf.format(new Date());
        savePath += ymd + "/";
        saveUrl += ymd + "/";
        File dirFile = new File(savePath);
        if (!dirFile.exists()) {
            dirFile.mkdirs();
        }*/

        if (file != null) {
        	// 获取上传文件名
            String fileName = file.getOriginalFilename();
            // 检查文件大小
            if (file.getSize() > maxSize) {
                throw new RuntimeException("上传文件大小超过限制。");
            }
            // 检查扩展名
            String fileExt = fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase();
            if (!Arrays.<String>asList(extMap.get(dirName).split(COMMA)).contains(fileExt)) {
                throw new RuntimeException("上传文件扩展名是不允许的扩展名。\n只允许" + extMap.get(dirName) + "格式。");
            }

            SimpleDateFormat df = new SimpleDateFormat("yyyyMMddHHmmss");
            String newFileName = df.format(new Date()) + "_" + new Random().nextInt(1000) + "." + fileExt;
            try {
                File uploadedFile = new File(savePath, newFileName);
                // 将上传文件写到服务器上指定的文件夹
                file.transferTo(uploadedFile);
            } catch (Exception e) {
                throw new RuntimeException("上传文件失败");
            }
            url = saveUrl + newFileName;
        }
        return url;
    }

    /**
     * 删除文件
     * @param fileName
     * @return
     */
    public static boolean deleteFile(String fileName) {
        logger.info("=====删除开始=====");
        // 读取imgPath配置文件
        ResourceBundle rb = ResourceBundle.getBundle ( "sysConfig" , Locale.getDefault ());
        //硬盘存放路径
        String savePath = rb.getString( "fileRealPath" );
        //相对路径
        String saveUrl = rb.getString( "filePath" );
        String truePath = fileName.replace(saveUrl, "");
        File file = new File(savePath + truePath);
        if (file.exists() && file.isFile()) {
            if (file.delete()) {
                logger.info("=====删除成功=====");
                return true;
            } else {
                logger.info("=====删除失败=====");
                return false;
            }
        } else {
            logger.debug("=====删除失败=====",new BusinessException("文件不存在"));
            return false;
        }
    
    }
    
    /**
     * 下载
     * @param request
     * @param url
     * @param fileName
     * @return
     * @throws IOException
     */
    @SuppressWarnings("resource")
    public static ResponseEntity<byte[]> download(HttpServletRequest request, String url, String fileName) throws IOException{
        // 读取imgPath配置文件
        ResourceBundle rb = ResourceBundle.getBundle ( "sysConfig" , Locale.getDefault ());
        String savePath = rb.getString( "fileRealPath" );
        String saveUrl = rb.getString( "filePath" );
        String truePath = url.replace(saveUrl, "");
        File file = new File(savePath + truePath);
        byte[] body = null;
        InputStream is = new FileInputStream(file);
        body = new byte[is.available()];
        is.read(body);
        HttpHeaders headers = new HttpHeaders();
        headers.add("Content-Disposition", "attchement;filename=" + fileName);
        HttpStatus statusCode = HttpStatus.OK;
        ResponseEntity<byte[]> entity = new ResponseEntity<byte[]>(body, headers, statusCode);
        return entity;
    }
    
    /**
     * 下载
     * @param fileName
     * @param filePath
     * @param request
     * @param response
     * @throws Exception
     */
    public static void download(String fileName, String filePath, HttpServletRequest request,
            HttpServletResponse response) throws Exception {
        // 读取imgPath配置文件
        ResourceBundle rb = ResourceBundle.getBundle ( "sysConfig" , Locale.getDefault ());
        String savePath = rb.getString( "fileRealPath" );
        String saveUrl = rb.getString( "filePath" );
        String fileExt = "." + filePath.substring(filePath.lastIndexOf(".") + 1).toLowerCase();
        // 设置响应头和客户端保存文件名
        response.reset();// 重置输出流
        response.setCharacterEncoding("utf-8");
        response.setContentType("multipart/form-data");
        response.setHeader("Content-Disposition", "attachment;fileName=" + new String(fileName.getBytes(), "iso8859-1") + fileExt);
        try {
            String truePath = filePath.replace(saveUrl, "");
            // 打开本地文件流
            InputStream inputStream = new FileInputStream(savePath + truePath);
            // 激活下载操作
            OutputStream os = response.getOutputStream();

            // 循环写入输出流
            byte[] b = new byte[2048];
            int length;
            while ((length = inputStream.read(b)) > 0) {
                os.write(b, 0, length);
            }
            os.close();
            inputStream.close();
        } catch (Exception e) {
            throw e;
        }
    }
    
    /**
     * 检测文件是否存在
     * @param filePath
     * @return
     */
    public static boolean checked(String filePath){
        boolean is = false;
        // 读取imgPath配置文件
        ResourceBundle rb = ResourceBundle.getBundle ( "sysConfig" , Locale.getDefault ());
        String savePath = rb.getString( "fileRealPath" );
        String saveUrl = rb.getString( "filePath" );
        
        String truePath = filePath.replace(saveUrl, "");
        File file = new File(savePath + truePath);
        if(file.exists() && file.isFile()){
            is = true;
        } 
        return is;
    }
    
    private static HashMap<String, String> getType(String identifier) {
        HashMap<String, String> extMap = new HashMap<String, String>(16);
        ResourceBundle rb = ResourceBundle.getBundle("sysConfig", Locale.getDefault());
        if (IMAGE.equals(identifier)) {
            extMap.put(IMAGE, rb.getString(IMAGE));
        } else if (FLASH.equals(identifier)) {
            extMap.put(FLASH, rb.getString(FLASH));
        } else if (MEDIA.equals(identifier)) {
            extMap.put(MEDIA, rb.getString(MEDIA));
        } else if (FILE.equals(identifier)) {
            extMap.put(FILE, rb.getString(FILE));
        }
        return extMap;
    }
}
